import Post from "../models/Post.js"
import User from "../models/User.js"
import { postRegex } from "../instrument/regEx/index.js"
import { getTime } from '../instrument/time/index.js'
import { Op } from "sequelize"

// 错误处理函数
const handleError = (ctx, message, status = 400) => {
  ctx.status = status
  ctx.body = { message }
}

// 数据验证函数
const validatePostData = async ({ title, content }) => {
  const validation = await postRegex({ title, content })
  if (!validation.valid) {
    throw new Error(validation.message)
  }
}

const fn_PostAllData = async ctx => {
  let { userName, keyword } = ctx.request.query
  let where = userName ? { '$User.userName$': userName } : null
  if (keyword) {
    where = {
      [Op.or]: {
        title: {
          [Op.like]: `%${keyword}%`
        }
      }
    }
  }
  try {
    const data = await Post.findAll({
      where,
      include: [
        {
          model: User,
          as: 'User',
          attributes: ['id', 'userName']
        }
      ],
      attributes: ['id', 'title', 'createdAt', 'updatedAt', 'views', 'userID']
    })
    ctx.status = 200;
    ctx.body = {
      message: '获取数据成功',
      data: (data.map(item => ({
        id: item.id,
        title: item.title,
        createdAt: getTime(item.createdAt),
        updatedAt: getTime(item.updatedAt),
        views: item.views,
        userName: item.User.dataValues.userName
      }))).reverse()
    }
  } catch (error) {
    handleError(ctx, '获取数据失败', 500);
  }
}

// 获取单篇文章数据
const fn_PostOneData = async ctx => {
  let id = ctx.request.params.id
  try {
    const data = await Post.findAll({ where: { id } })
    ctx.status = 200
    ctx.body = { message: '获取数据成功', data }
  } catch (error) {
    handleError(ctx, '获取数据失败', 500)
  }
}

// 添加文章
const fn_PostAdd = async ctx => {
  let { title, content, userID } = ctx.request.body
  try {
    await validatePostData({ title, content })
    const res = await Post.create({ title, content, userID })
    ctx.status = 200
    ctx.body = { message: '文章创建成功', res }
  } catch (error) {
    handleError(ctx, error.message)
  }
}

// 更新文章
const fn_PostUpdate = async ctx => {
  let { title, content, userID } = ctx.request.body
  let id = ctx.request.params.id
  try {
    await validatePostData({ title, content })
    const res = await Post.update({ title, content }, { where: { id, userID } })
    if (res > 0) {
      ctx.status = 200
      ctx.body = { message: '文章修改成功', res }
    } else {
      handleError(ctx, '无修改权限或并未找到需要修改的文章')
    }
  } catch (error) {
    handleError(ctx, error.message)
  }
}
const fn_PostUpdateView = async ctx => {
  let id = ctx.request.params.id;
  try {
    let obj = await Post.findAll({ where: { id } })
    if (!obj || obj.length === 0) {
      ctx.status = 404
      ctx.body = { message: '文章不存在' }
      return
    }
    let currentViews = obj[0].dataValues.views
    const res = await Post.update(
      { views: currentViews + 1 },
      { where: { id } }
    )
    if (res > 0) {
      ctx.status = 200;
      ctx.body = { message: '文章观看数量更新成功', views: currentViews + 1 }
    } else {
      ctx.status = 400;
      ctx.body = { message: '文章观看数量更新失败' }
    }
  } catch (error) {
    handleError(ctx, error.message)
  }
}

// 删除文章
const fn_PostDelete = async ctx => {
  let userID = ctx.request.query.userID
  let id = ctx.request.params.id
  try {
    const res = await Post.destroy({ where: { id, userID } })
    if (res > 0) {
      ctx.status = 200
      ctx.body = { message: '文章删除成功', res }
    } else {
      handleError(ctx, '无删除权限或并未找到需要删除的文章')
    }
  } catch (error) {
    handleError(ctx, '文章删除失败', 500)
  }
}

export default [
  {
    method: 'get',
    url: '/api/post',
    fn: fn_PostAllData
  },
  {
    method: 'get',
    url: '/api/post/:id',
    fn: fn_PostOneData
  },
  {
    method: 'post',
    url: '/api/post',
    fn: fn_PostAdd
  },
  {
    method: 'put',
    url: '/api/post/:id',
    fn: fn_PostUpdate
  },
  {
    method: 'put',
    url: '/api/post/views/:id',
    fn: fn_PostUpdateView
  },
  {
    method: 'delete',
    url: '/api/post/:id',
    fn: fn_PostDelete
  }
]